package com.kang.c0c.tree.node;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;

import com.kang.c0c.optimize.DataRecode;
import com.kang.c0c.symbol.Symbol;

public class SimpleBlock extends Node{
	private Vector<LeafNode> unaryList;
	private Vector<BinaryNode> binaryList;
	private Hashtable<Symbol,Integer> value;
	
	public DataRecode data;
	
	public SimpleBlock next = null;
	public SimpleBlock prev = null;
	
	public SimpleBlock(){
		super(Nodes.SBLOCK);
		
		unaryList = new Vector<LeafNode>();
		binaryList = new Vector<BinaryNode>();		
		value = new Hashtable<Symbol,Integer>();
		data = new DataRecode(this);
	}
	
	public SimpleBlock(SimpleBlock simple){
		this();
		value = new Hashtable<Symbol,Integer>(simple.value);
	}
	
	public void unionValue(SimpleBlock simple){
		Hashtable<Symbol,Integer> temp = new Hashtable<Symbol,Integer>();
		
		Set<Symbol> set = this.value.keySet();
		set.retainAll(simple.value.keySet());
		Iterator<Symbol> keys = set.iterator();
		
		while(keys.hasNext()){
			Symbol sym = keys.next();
			Integer int1 = this.value.get(sym);
			Integer int2 = simple.value.get(sym);
			
			if((int1 != null)&&(int2 != null))
				if(int1 == int2)
					temp.put(sym, int1);
		}
	}
	
	public void cleanBlock(){
		boolean change = true;
		while(change){
			change = false;
			int i=0;
			
			while(i < binaryList.size()){
				if(binaryList.elementAt(i).getUse() == 0){					
					removeBinary(i);
					change = true;
				}else
					i++;
			}
			
			i=0;
			while(i < unaryList.size()){
				if(unaryList.elementAt(i).getUse() == 0){
					removeUnary(i);
				}else
					i++;
			}
		}
		
		/*
		 * 销毁使用完的对象，释放一定量的空间
		 */
		this.value = null;
	}
	
	/**
	 * 赋值语句的转化
	 * 
	 * @param left	赋值语句的左节点，也就是被赋值的对象
	 * @param right	赋值语句的右节点，也就是被使用的赋值
	 */
	public void insertEva(LeafNode left, Node right){
		int leftIndex = insertUnary(left);
		left = getUnary(leftIndex);
		
		updateValue(left,right);
		//delUnuseEva(left);
		
		BinaryNode node = new BinaryNode(Nodes.EVA,
				left,right);
		
		binaryList.add(node);
		if(node.getRight() != null)
			node.getRight().incUse();
		int index = binaryList.size() - 1;
		binaryList.elementAt(index).incUse();
	}
	
	/**
	 * 赋值语句转化过程中将被调用，主要是为了刷新基本块内到达定值中的常量，为后面的传播作准备
	 * 
	 * @param left
	 * @param right
	 */
	public void updateValue(LeafNode left, Node right){
		Integer number = null;
		
		if((right != null)
				&&(right instanceof LeafNode)){
			LeafNode rightT = (LeafNode)right;
			
			if(rightT.getNode() == Nodes.NUM){
				number = (Integer)rightT.getValue();
			}else if(rightT.getNode() == Nodes.VAR){
				Symbol sym = (Symbol)rightT.getValue();
				number = value.get(sym);
			}
		}
		
		Symbol sym = (Symbol)left.getValue();
		if(value.get(sym) != null){
			value.remove(sym);
		}
		
		if(number != null)
			value.put(sym, number);
	}
	
	/**
	 * 删除基本块内没有用到的赋值语句
	 * 
	 * @param leaf	被赋值的左节点
	 */
	/*private void delUnuseEva(LeafNode leaf){
		if(leaf == null)
			return ;
		
		int i = binaryList.size() - 1;
		while(i >=0){
			if(binaryList.elementAt(i).getNode() == Nodes.EVA){
				LeafNode leafT = (LeafNode)binaryList.elementAt(i).getLeft();
				if(leaf.equal(leafT)){
					int leafIndex = 0;
					while(leafIndex < unaryList.size()){
						if(unaryList.elementAt(leafIndex).equals(leafT))
							break;
						leafIndex ++;
					}
					
					if(unaryUse.elementAt(leafIndex) == 1){
						removeBinary(i);
						removeUnary(leafIndex);
					}
					
					return ;
				}
			}
			i--;
		}
	}*/
	
	/*
	 * **************************************************************
	 */
	public Integer getValue(int index){
		LeafNode leaf = getUnary(index);
		
		if(leaf == null)
			return null;
		
		if(leaf.getNode() == Nodes.NUM)
			return (Integer)leaf.getValue();
		
		if(leaf.getNode() == Nodes.VAR)
			return value.get(leaf.getValue());
		
		return null;
	}
	
	public int lookForUnary(LeafNode leaf){
		int i = unaryList.size() - 1;
		
		if(leaf == null)
			return -1;
		
		while(i >= 0){
			if(leaf.equal(unaryList.elementAt(i)))
				return i;
			
			i --;
		}
		
		return insertUnary(leaf);
	}
	
	public LeafNode getUnary(int index){
		if((index < 0)
				||(index >= unaryList.size()))
				return null;
		
		return unaryList.elementAt(index);
	}
	
	public int lookForBinary(BinaryNode binary){
		int i = binaryList.size() - 1;
		
		if(binary == null)
			return -1;
		
		while(i >= 0){
			if(binary.equal(binaryList.elementAt(i)))
				return i;
			
			i--;
		}
		
		return insertBinary(binary);
	}
	
	public BinaryNode getBinary(int index){
		if((index < 0)
				||(index >= binaryList.size()))
			return null;
		
		return binaryList.elementAt(index);
	}
	
	/*
	 * insert item
	 */	
		
	public int insertUnary(LeafNode leaf){
		unaryList.add(leaf);
		
		return unaryList.size()-1;
	}
		
	public int insertBinary(BinaryNode binary){
		binaryList.add(binary);
		
		if(binary.getLeft() != null)
			binary.getLeft().incUse();
		if(binary.getRight() != null)
			binary.getRight().incUse();
		
		return binaryList.size()-1;
	}
	
	/*
	 * remove item
	 */
	public void removeUnary(int index){
		if((index < 0)
				||(index >= unaryList.size()))
			return;
		
		unaryList.remove(index);
	}
	
	public void removeLast(){
		int index = binaryList.size() - 1;
		if(index > 0)
			binaryList.remove(index);			
	}
	
	public void removeFirst(){
		if(binaryList.size() > 0)
			binaryList.remove(0);
	}
	
	public void removeBinary(int index){
		if((index < 0)
				||(index >= binaryList.size()))
			return;
		
		BinaryNode binary = binaryList.elementAt(index);
		if(binary.getLeft() != null)
			binary.getLeft().decUse();
		if(binary.getRight() != null)
			binary.getRight().decUse();
		
		binaryList.remove(index);
	}

	public int binarySize(){
		return binaryList.size();
	}
}